package com.efeichong.oss;

import com.efeichong.exception.BaseException;
import lombok.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.web.multipart.MultipartFile;

import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipOutputStream;

/**
 * @author lxk
 * @date 2020/11/5
 * @description oss抽象类, 处理文件的上传/下载/删除
 */
public abstract class AbstractOssService {
    /**
     * 区域
     */
    protected String region;
    /**
     * 表示OSS对外服务的访问域名
     */
    protected String endpoint;
    /**
     * 访问密钥  用于标识用户
     */
    protected String accessKeyId;
    /**
     * 访问密钥  用户用于加密签名字符串和OSS用来验证签名字符串的密钥
     */
    protected String accessKeySecret;

    /**
     * 根路径 如：opt,D盘
     */
    protected String baseDir;
    /**
     * 展示的时候将以这个值替换根路径
     */
    protected String viewUrlPrefix;
    /**
     * 上传返回的图片路径域名
     */
    protected String showDomainUrl;

    /**
     * 非本地配置加载
     *
     * @param config
     */
    public AbstractOssService(@NonNull final OssConfigS3 config) {
        if (StringUtils.isBlank(config.getEndPoint())) {
            throw new BaseException("请配置存endpoint");
        }
        if (StringUtils.isBlank(config.getAccessKeyId())) {
            throw new BaseException("请配置accessKeyId");
        }
        if (StringUtils.isBlank(config.getAccessSecret())) {
            throw new BaseException("请配置accessKeySecret");
        }
        endpoint = config.getEndPoint();
        accessKeyId = config.getAccessKeyId();
        accessKeySecret = config.getAccessSecret();
        region = config.getRegion();
    }

    /**
     * 本地配置加载
     *
     * @param config
     */
    public AbstractOssService(@NonNull final OssConfigLocal config) {
        if (StringUtils.isBlank(config.getBaseDir()) || StringUtils.isBlank(config.getViewUrlPrefix())) {
            throw new BaseException("请配置存储路径及展示路径");
        }
        this.baseDir = handlePath(config.getBaseDir());
        this.viewUrlPrefix = handlePath(config.getViewUrlPrefix());
        this.showDomainUrl = config.getShowDomainUrl();
    }

    /**
     * 将路径的后斜杠去掉
     *
     * @param path
     * @return
     */
    private static String handlePath(String path) {
        if (path.endsWith("/")) {
            return path.substring(0, path.length() - 1);
        } else {
            return path;
        }
    }

    /**
     * 文件上传
     *
     * @param file       文件
     * @param bucketName 指定空间 本地指定根目录，云服务指定存储桶
     * @param folderName 文件路径
     * @return
     */
    protected String upload(@Nullable MultipartFile file, @Nullable String bucketName, @Nullable String folderName, @NonNull String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 文件上传
     *
     * @param files      文件
     * @param bucketName 指定空间 本地指定根目录，云服务指定存储桶
     * @param folderName 文件路径
     * @return
     */
    protected List<String> upload(@Nullable MultipartFile[] files, @Nullable String bucketName, @Nullable String folderName, @NonNull String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 文件上传
     *
     * @param bytes      文件字节数组
     * @param folderName 文件路径
     * @param suffix     文件后缀
     * @return
     */
    protected String upload(@Nullable byte[] bytes, @Nullable String bucketName, @Nullable String folderName, @NonNull String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 文件上传
     *
     * @param file       文件
     * @param folderName 文件路径
     * @return
     */
    protected String upload(@Nullable MultipartFile file, @Nullable String folderName, @NonNull String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 文件上传
     *
     * @param bytes      文件字节数组
     * @param folderName 文件路径
     * @param suffix     文件后缀
     * @return
     */
    protected String upload(@Nullable byte[] bytes, @Nullable String folderName, @Nullable String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 文件上传
     *
     * @param files      文件
     * @param folderName 文件路径
     * @return
     */
    protected List<String> upload(@Nullable MultipartFile[] files, @Nullable final String folderName, @NonNull String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 获取临时授权的地址
     *
     * @param bucketName 指定空间
     * @param folderName 文件路径
     * @return
     */
    protected UploadUrl getUploadUrl(@Nullable String bucketName, @Nullable String folderName, @Nullable String suffix) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 获取临时授权的地址
     *
     * @param bucketName 指定空间
     * @param folderName 文件路径
     * @return
     */
    protected List<UploadUrl> getUploadUrls(@Nullable String bucketName, @Nullable String folderName, @Nullable String suffix, @Nullable Integer num) {
        throw new BaseException("不支持此功能");
    }

    /**
     * 下载文件
     *
     * @param url 文件地址
     */
    public abstract byte[] download(@Nullable String url);

    /**
     * 批量下载
     *
     * @param outputStream
     * @param urls         文件地址
     */
    public abstract ZipOutputStream batchDownload(@Nullable OutputStream outputStream, @Nullable List<String> urls);

    /**
     * 删除
     *
     * @param url 文件地址
     */
    public abstract void delete(@Nullable String url);

    /**
     * 批量删除
     *
     * @param urls 文件地址
     */
    public abstract void batchDelete(@Nullable List<String> urls);

}
